#include "udpcomm.h"
#include <QMessageBox>

udpComm::udpComm(QWidget *parent)
        : QMainWindow(parent)
{
    this->resize(800, 500);
    QWidget *central = new QWidget(this);
    this->setCentralWidget(central);

    // 布局
    QVBoxLayout *mainLayout = new QVBoxLayout(central);
    QHBoxLayout *topLayout = new QHBoxLayout;
    QHBoxLayout *midLayout = new QHBoxLayout;

    // 控件初始化
    spinBoxbindport = new QSpinBox;
    spinBoxbindport->setMaximum(65535);
    spinBoxbindport->setValue(1567);

    spinBoxtargetport = new QSpinBox;
    spinBoxtargetport->setMaximum(65535);
    spinBoxtargetport->setValue(1568);

    comboBoxtargetip = new QComboBox;
    comboBoxtargetip->addItem(GetLocalIpAddress());

    pushButton_start = new QPushButton("启动服务");
    pushButton_stop = new QPushButton("停止服务");
    pushButton_stop->setEnabled(false);

    lineEditmsg = new QLineEdit;
    pushButton_sendmsg = new QPushButton("发送消息");
    pushButton_broadcastmsg = new QPushButton("广播消息");

    plainTextEditdispmsg = new QPlainTextEdit;
    plainTextEditdispmsg->setReadOnly(true);

    // 添加控件到布局
    topLayout->addWidget(new QLabel("源端口:"));
    topLayout->addWidget(spinBoxbindport);
    topLayout->addWidget(new QLabel("目标IP:"));
    topLayout->addWidget(comboBoxtargetip);
    topLayout->addWidget(new QLabel("目标端口:"));
    topLayout->addWidget(spinBoxtargetport);
    topLayout->addWidget(pushButton_start);
    topLayout->addWidget(pushButton_stop);

    midLayout->addWidget(lineEditmsg);
    midLayout->addWidget(pushButton_sendmsg);
    midLayout->addWidget(pushButton_broadcastmsg);

    mainLayout->addLayout(topLayout);
    mainLayout->addLayout(midLayout);
    mainLayout->addWidget(plainTextEditdispmsg);

    // 初始化 socket
    udpsocket = new QUdpSocket(this);
    connect(udpsocket, &QUdpSocket::readyRead, this, &udpComm::SocketReadyReadData);

    // 信号连接
    connect(pushButton_start, &QPushButton::clicked, this, &udpComm::on_pushButton_start_clicked);
    connect(pushButton_stop, &QPushButton::clicked, this, &udpComm::on_pushButton_stop_clicked);
    connect(pushButton_sendmsg, &QPushButton::clicked, this, &udpComm::on_pushButton_sendmsg_clicked);
    connect(pushButton_broadcastmsg, &QPushButton::clicked, this, &udpComm::on_pushButton_broadcastmsg_clicked);
}

udpComm::~udpComm()
{
    delete udpsocket;
}

QString udpComm::GetLocalIpAddress()
{
    QString hostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString localIP;

    QList<QHostAddress> addresses = hostInfo.addresses();
    for (const QHostAddress &addr : addresses) {
        if (addr.protocol() == QAbstractSocket::IPv4Protocol && !addr.isLoopback()) {
            localIP = addr.toString();
            break;
        }
    }
    return localIP;
}

void udpComm::on_pushButton_start_clicked()
{
    quint16 port = spinBoxbindport->value();
    if (udpsocket->bind(port)) {
        plainTextEditdispmsg->appendPlainText("**********绑定成功**********");
        plainTextEditdispmsg->appendPlainText("绑定端口: " + QString::number(udpsocket->localPort()));
        pushButton_start->setEnabled(false);
        pushButton_stop->setEnabled(true);
    } else {
        plainTextEditdispmsg->appendPlainText("**********绑定失败**********");
    }
}

void udpComm::on_pushButton_stop_clicked()
{
    udpsocket->abort();
    pushButton_start->setEnabled(true);
    pushButton_stop->setEnabled(false);
    plainTextEditdispmsg->appendPlainText("**********服务已停止**********");
}

void udpComm::on_pushButton_sendmsg_clicked()
{
    QString ip = comboBoxtargetip->currentText();
    quint16 port = spinBoxtargetport->value();
    QString msg = lineEditmsg->text();
    QByteArray data = msg.toUtf8();

    udpsocket->writeDatagram(data, QHostAddress(ip), port);

    plainTextEditdispmsg->appendPlainText("[发送]：" + msg);
    lineEditmsg->clear();
    lineEditmsg->setFocus();
}

void udpComm::on_pushButton_broadcastmsg_clicked()
{
    quint16 port = spinBoxtargetport->value();
    QString msg = lineEditmsg->text();
    QByteArray data = msg.toUtf8();

    udpsocket->writeDatagram(data, QHostAddress::Broadcast, port);

    plainTextEditdispmsg->appendPlainText("[广播]：" + msg);
    lineEditmsg->clear();
    lineEditmsg->setFocus();
}

void udpComm::SocketReadyReadData()
{
    while (udpsocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(int(udpsocket->pendingDatagramSize()));

        QHostAddress sender;
        quint16 senderPort;

        udpsocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        QString msg = QString("[来自 %1:%2]：%3")
                .arg(sender.toString())
                .arg(senderPort)
                .arg(QString::fromUtf8(datagram));
        plainTextEditdispmsg->appendPlainText(msg);
    }
}
